//////////////////////////////////////////////////////////////////
// MattiseOS Kernel
// Date: 2008
// Author: Matthew Iselin
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//////////////////////////////////////////////////////////////////

#ifndef MEMUTIL_H
#define MEMUTIL_H

// Includes
#include <mattise.h>

// Types

struct page
{
	uint32_t present    : 1;   // Page present in memory
	uint32_t rw         : 1;   // Read-only if clear, readwrite if set
	uint32_t user       : 1;   // Supervisor level only if clear
	uint32_t accessed   : 1;   // Has the page been accessed since last refresh?
	uint32_t dirty      : 1;   // Has the page been written to since last refresh?
	uint32_t unused     : 7;   // Amalgamation of unused and reserved bits
	uint32_t frame      : 20;  // Frame address (shifted right 12 bits)
} __attribute__((packed));

struct page_table_int // integers
{
	uint32_t pages[1024];
};

struct page_table_str // structs
{
	struct page pages[1024];
};

struct page_directory
{
	uint32_t page_tables[1024];
};

// Defines

// paging flags
#define PF_PRESENT		0x1
#define PF_READWRITE	0x2
#define PF_SUPERVISOR	0x0
#define PF_USER			0x4
#define PF_GLOBAL		0x100
#define PF_KERNELPAGE	0x200
#define PF_IMMUTABLE	0x400

// prefer speed or size?
#define PREFER_SPEED 1

// the kernel heap base
#define KERNEL_HEAP_BASE	0xb0000000

// External Variables

// the total available memory
#ifndef KERNEL_MAIN_FILE
extern uint32_t total_avail_mem;
#endif

// Prototypes

// dlmalloc support
void* dlmalloc_extend_heap(int32_t amt);
void dlmalloc_abort(const char* source);

// sets memory to a certain value
//void memset( const void* p, uint8_t val, size_t len );
void* memset(const void* m, unsigned char c, size_t n);

// copies memory from one location to another
void* memcpy( void* d, const void* s, size_t len );

// sets up paging
void kInitPaging();

// loads CR3 with a specific address
void kLoadCR3( uint32_t addr );

// invalidates a mapping
inline void invlpg(uint32_t pg);

// gets the value of CR3
uint32_t kGetCR3();

// gets the kernel page directory (physical)
uint32_t GetKernelDirectory();

// gets a physical address for a page from a page directory
uint32_t GetPhysicalAddress( uint32_t pagedir, uint32_t page );

// changes the mapping of a physical page - if new_phys is zero then the physical
// address is NOT updated
void ChangeMapping( uint32_t paddr, uint32_t vaddr, uint32_t new_phys, uint32_t flags );

// clones a page directory (recopies everything)
void CloneDirectory( uint32_t dir, uint32_t destdir );

// maps a page into a page directory
void MapPage( uint32_t pagedir, uint32_t page, uint32_t phys, uint32_t flags );

// checks to see if a page is mapped
char IsMapped( uint32_t pagedir, uint32_t page );

// destroys the mapping for a specific page
void kDestroyPageMapping(uint32_t pagedir, uint32_t page, uint32_t free_phys);

// adjusts the reference counts
void kIncrRefCount( uint32_t page );

// reduces the reference count
void kDecrRefCount( uint32_t page );

// gets the reference count for a page
uint8_t kGetRefCount( uint32_t page );

#endif
